package com.jysz.certificate.service.cs;

import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.persistence.criteria.Subquery;

import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.springframework.stereotype.Service;

import com.jysz.certificate.persistence.dao.cs.CheckStockDao;
import com.jysz.certificate.persistence.dao.cs.CheckStockOptionDao;
import com.jysz.certificate.persistence.dao.system.OrganizationDao;
import com.jysz.certificate.persistence.dao.system.ShopDao;
import com.jysz.certificate.persistence.enums.AttachmentType;
import com.jysz.certificate.persistence.enums.PostType;
import com.jysz.certificate.persistence.enums.cs.CheckStockStatus;
import com.jysz.certificate.persistence.model.cm.Certification;
import com.jysz.certificate.persistence.model.cs.CheckStock;
import com.jysz.certificate.persistence.model.cs.CheckStockOption;
import com.jysz.certificate.persistence.model.cs.ShowItem;
import com.jysz.certificate.persistence.model.cs.ShowRow;
import com.jysz.certificate.persistence.model.cs.ShowTop;
import com.jysz.certificate.persistence.model.system.Financial;
import com.jysz.certificate.persistence.model.system.Organization;
import com.jysz.certificate.persistence.model.system.Shop;
import com.jysz.certificate.persistence.model.system.User;
import com.jysz.certificate.service.cm.CertificationService;
import com.jysz.certificate.service.core.AttachmentService;
import com.jysz.certificate.service.system.FinancialService;
import com.jysz.certificate.service.system.OrganizationService;
import com.jysz.certificate.utils.CommonUtil;
import com.jysz.certificate.utils.DateUtil;
import com.jysz.webcore.ssh.orm.hibernate.support.Page;
import com.jysz.webcore.ssh.service.EntityService;

/**
 * 盘库Service
 * @author xuxiaolong
 */
@Service
public class CheckStockService extends EntityService<CheckStock, Long, CheckStockDao> {

	@Resource
	private CheckStockDao csDao;
	@Resource
	private CheckStockOptionDao optionDao;
	@Resource
	private ShopDao shopDao;
	@Resource
	private OrganizationDao organizationDao;
	@Resource
	private OrganizationService orgService;
	@Resource
	private CertificationService cfService;
	@Resource
	private FinancialService bankService;
	@Resource
	private AttachmentService attService;
	@Override
	public CheckStockDao getEntityDao() {
		return this.csDao;
	}
	
	/**
	 * 盘库记录查询
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public Page<CheckStock> findPage(CheckStock search,int pageNumber,int pageSize){
		
		Criteria criteria=csDao.createCriteria();
//		criteria.addOrder(Order.asc("areaManager"));
		criteria.addOrder(Order.asc("status"));
		criteria.addOrder(Order.desc("finishDate"));
//		criteria.addOrder(Order.desc("updatedAt"));
		
		if(search!=null){
			//驻店员
			if(search.getShopUser()!=null&&CommonUtil.isNotEmpty(search.getShopUser().getRealName()))
				criteria.createCriteria("shopUser").add(Restrictions.like("realName", search.getShopUser().getRealName(),MatchMode.ANYWHERE));
			//店号
			if(search.getShop()!=null&&CommonUtil.isNotEmpty(search.getShop().getShopMark())){
				Criteria shopCriteria=criteria.createCriteria("shop").add(Restrictions.like("shopMark", search.getShop().getShopMark(),MatchMode.ANYWHERE));
				csDao.addShopCriteria(shopCriteria, true, null);
			}else{
				csDao.addShopCriteria(criteria, false, null);
			}
			//区域经理
			if(search.getAreaManager()!=null&&CommonUtil.isNotEmpty(search.getAreaManager().getRealName()))
				criteria.createCriteria("areaManager").add(Restrictions.like("realName", search.getAreaManager().getRealName(),MatchMode.ANYWHERE));
			//状态
			if(search.getStatus()!=null)
				criteria.add(Restrictions.eq("status", search.getStatus()));
			//盘库日期-开始
			if(search.getCreatedAt()!=null)
				criteria.add(Restrictions.ge("finishDate", DateUtil.getBeginDate(search.getCreatedAt())));
			//盘库日期-结束
			if(search.getUpdatedAt()!=null)
				criteria.add(Restrictions.le("finishDate",DateUtil.getEndDate(search.getUpdatedAt())));
			//盘库结果
			if(search.getSuccess()!=null){
				criteria.add(Restrictions.eq("success", search.getSuccess()));
			}
		}else{
			csDao.addShopCriteria(criteria, false, null);
		}
		
		return this.findPage(criteria, pageNumber, pageSize);
	}
	
	/** 新增*/
	public void create(CheckStock cs){
		buildOptions(cs);
		super.save(cs);
	}
	
	/** 暂存*/
	public void save(CheckStock cs,File file,String fileName,User user){
		super.save(cs);
		//上传附件
		if(file!=null)
			attService.addFile(user, AttachmentType.CHECKSTOCK, file, cs.getId(),fileName);
	}
	
	/** 重新盘库*/
	public void reset(Long id){
		//盘库单状态置为 已发起
		CheckStock cs= this.find(id);
		cs.setStatus(CheckStockStatus.UNSTART);
		cs.setRemark(null);
		
		for(CheckStockOption option:cs.getOptions()){
			/*option.setCfStatus(null);
			option.setCfStatusArea(null);
			option.setCarStatus(null);
			option.setCarStatusArea(null);
			option.setRemark(null);*/
			optionDao.destory(option);
		}
		cs.setOptions(null);
		buildOptions(cs);
		super.save(cs);
		
		//删除附件
		attService.delFile(id, AttachmentType.CHECKSTOCK);
	}
	
	/** 删除*/
	public void destory(Long id){
		
		//删除盘库
		super.destory(id);
		//删除附件
		attService.delFile(id, AttachmentType.CHECKSTOCK);
	}
	
	/**
	 * 根据月份和是否是总部盘库，确定盘库单在行中所显示的位置
	 * @param month 
	 * @param live 是总部
	 * @return
	 */
	public int getIndex(String month,int source,String monthAry[]){
		int index=0,i=0;
		for(String str:monthAry){
			
			if(str.equals(month)){
				if(source!=2)
					index=2*i+1;
				else
					index=2*i;
			}
			i++;	
		}
		return index;
	}
	
	//获得月份区间
	private String[] getMonthAry(List<Map<String,Object>> list){
		List<String> l=new ArrayList<String>();
		String tmp=null;
		for(int i=0;i<list.size();i++){
			Map<String,Object> map = (Map)list.get(i);
			tmp=map.get("csDate").toString();
			if(!l.contains(tmp))
				l.add(tmp);
			
		}
		
		return (String[]) l.toArray(new String[l.size()]);
	}
	
	/**
	 * 盘库汇总查询
	 * @param top 前三行
	 * @param rowList
	 * @param beginDate
	 * @param endDate
	 */
	public List<Map<String, Object>> search(User currentUser,ShowTop top,LinkedList<ShowRow> rowList,Date beginDate,Date endDate,int status,int success){

		List<Financial> bankList=bankService.finList();
		List<Map<String,Object>> list=csDao.search(currentUser,bankList,beginDate,endDate,success);
		String bankAry[]=getBankAry(bankList);
//		String monthAry[]=DateUtil.getBetweenMonthAry(beginDate, endDate);
		String monthAry[]=getMonthAry(list);//过滤没有盘库记录的月份
		buildTop(top, monthAry, bankAry);
		int column=monthAry.length*2;
		//店铺-modelList
		Map<Long,Map[]> rusMap=new HashMap<Long,Map[]>();
		
		//按店铺归类
		for(int i=0;i<list.size();i++){
			Map<String,Object> map = (Map)list.get(i);
			Long shopId=((BigInteger)map.get("shopId")).longValue();
			if(rusMap.containsKey(shopId)){
				int index=getIndex(map.get("csDate")+"",Integer.valueOf(map.get("source").toString()),monthAry);
				rusMap.get(shopId)[index]=map;
			}else{
				Map[] tmp=new Map[column];
				int index=getIndex(map.get("csDate")+"",Integer.valueOf(map.get("source").toString()),monthAry);
				tmp[index]=map;
				rusMap.put(shopId, tmp);
			}
		}
		
		//构建 行集合	
		if(rowList==null)
			rowList=new LinkedList<ShowRow>();
		int i=0;
		for(Long key:rusMap.keySet()){
			if(status!=0){//--查询已盘或全部
				Long csId=1L;
				Shop shop=shopDao.find(key);//search Key
				ShowRow row=new ShowRow();
				row.setIndex(i++);
				row.setShopNum(shop.getShopMark());
				row.setShopName(shop.getShopName());
				Map[] tmp=rusMap.get(key);
				
				LinkedList<ShowItem> itemList=new LinkedList<ShowItem>();
				for(int j=0;j<tmp.length;j++){
					ShowItem item=new ShowItem();
					Map itemMap=tmp[j];
					if(itemMap!=null){
						item.setCsdate(itemMap.get("csDate")+"");
						item.setSubmitDate(itemMap.get("submitDate")+"");
						item.setCsid(((BigInteger)itemMap.get("csId")).longValue());
						csId=item.getCsid();
						item.setCsway(""+itemMap.get("live"));
						if(itemMap.get("opremark")!=null&&CommonUtil.isNotEmpty(itemMap.get("opremark").toString()))
							item.setRemark(itemMap.get("opremark").toString());
						LinkedList<String> numberList=new LinkedList<String>();
						for(int b=0;b<bankAry.length;b++){
							BigDecimal bi=(BigDecimal)itemMap.get(bankAry[b]);
							if(bi!=null)
								numberList.add(bi.toString());
							else
								numberList.add("");
						}
						item.setNumberList(numberList);
					}else{
						item=ShowItem.buildEmptyShowItem(bankAry.length);//构建空的盘库记录占位
					}
					
					itemList.add(item);
				}
				row.setItemList(itemList);
				CheckStock cs= this.find(csId);
				row.setShopUser(cs.getShopUser().getRealName());
				row.setAreaManager(cs.getAreaManager().getRealName());
				rowList.add(row);
			}
		}
		List<Map<String, Object>> emptyList=new ArrayList<Map<String,Object>>();
		//没有盘库记录的店铺。构建空的行
		if(status!=1){//--查询未盘或全部
			emptyList=csDao.search(currentUser, beginDate, endDate);
		}
		return emptyList;
	}
	
	/**
	 * 构建头部三行
	 * @param top
	 * @param monthAry 月份数组
	 * @param bankAry  银行名称数组
	 */
	public void buildTop(ShowTop top,String []monthAry,String []bankAry){
		if(top==null)
			top =new ShowTop();
		LinkedHashMap<String, Integer> rowOne=new LinkedHashMap<String, Integer>();
		rowOne.put("", 5);
		for(String month:monthAry){
			rowOne.put(month, 2*(bankAry.length+3));
		}
		
		LinkedHashMap<String, Integer> rowTwo=new LinkedHashMap<String, Integer>();
		rowTwo.put("", 5);
		int j=0;
		for(String month:monthAry){
			j++;
			rowTwo.put("银行_"+j, bankAry.length);
			rowTwo.put("区域经理盘查_"+j, 3);
			rowTwo.put("银行_"+ ++j, bankAry.length);
			rowTwo.put("总部盘查_"+j, 3);
		}
		
		LinkedHashMap<String, Integer> rowThree=new LinkedHashMap<String, Integer>();
		rowThree.put("序号", 1);
		rowThree.put("店号", 1);
		rowThree.put("销售店", 1);
		rowThree.put("驻店员", 1);
		rowThree.put("区域经理", 1);
		int k=0;
		for(String month:monthAry){
			k++;
			//区域经理
			for(String bank:bankAry){
				rowThree.put(bank+"_"+k, 1);
			}
			rowThree.put("盘库方式_"+k, 1);
			rowThree.put("盘库日期_"+k, 1);
			rowThree.put("备注_"+k, 1);
			k++;
			//总部
			for(String bank:bankAry){
				rowThree.put(bank+"_"+k, 1);
			}
			rowThree.put("盘库方式_"+k, 1);
			rowThree.put("盘库日期_"+k, 1);
			rowThree.put("备注_"+k, 1);
			
		}
		
		top.setRowOne(rowOne);
		top.setRowTwo(rowTwo);
		top.setRowThree(rowThree);
		
	}
	
	/** 新增盘库 包含所有在库合格证*/
	public void buildOptions(CheckStock cs){
		List<Certification> list=cfService.findList(cs.getShop().getId());
		if(!CommonUtil.isEmptyList(list)){
			List<CheckStockOption> options=new ArrayList<CheckStockOption>();
			CheckStockOption op=null;
			for(Certification cf:list){
				op=new CheckStockOption();
				op.setCheckStock(cs);
				op.setCertification(cf);
				options.add(op);
			}
			cs.setOptions(options);
		}
		
	}
	
	public String[] getBankAry(List<Financial> list){
		
		if(CommonUtil.isEmptyList(list))
			return null;
		String [] ary=new String[list.size()];
		for(int i=0;i<list.size();i++){
			ary[i]=list.get(i).getBrief();
		}
		return ary;
	}
	/**
	 * 查询本月还有多少店铺未盘库、或未完成盘库
	 * @param shopId
	 * @param user
	 * @return
	 */
	public Integer noCheckStoc(List<Shop> shops, User user){

		DetachedCriteria criteria = DetachedCriteria.forClass(CheckStock.class);
//		Criteria criteria = csDao.createCriteria();
		criteria.setProjection(Projections.groupProperty("shop"));
//		csDao.addShopCriteria(criteria, false, user);//添加权限过滤.考虑管理员
		criteria.add(Restrictions.in("shop", shops));
//		criteria.add(Restrictions.eq("sponsor.id", user.getId()));
		criteria.add(Restrictions.eq("source", user.getPost()));//只查询当前用户角色的
		criteria.add(Restrictions.between("finishDate", DateUtil.getFirstdayLastdayMonthOne(new Date()), DateUtil.getFirstdayLastdayMonthQuarter(new Date())));
		
		Criteria shopCriteria = this.shopDao.createCriteria();
		shopCriteria.setProjection(Projections.rowCount());
		shopCriteria.add(Property.forName("id").in(criteria));
		
		return ((Number)shopCriteria.uniqueResult()).intValue();
		
//		List<CheckStock> checkStocks = criteria.list();
//		if(!CommonUtil.isEmptyList(checkStocks)){
//			return checkStocks.size();
//		}
//		return 0;
		
	}
	/**
	 * 盘库发起状态数量
	 * @param shopId 销售店ID
	 * @param user  发起人
	 * @param checkStockStatus 盘库单状态
	 * @param postType 盘库来源
	 * @param shopUser 驻店员
	 * @param areaManager 区域经理
	 * @return
	 */
	public Integer noCheckStocOption(Long[] shopId,User user,CheckStockStatus checkStockStatus,PostType postType,User shopUser,User areaManager){
		Criteria criteria=csDao.createCriteria();
		criteria.add(Restrictions.in("shop.id", shopId));
		if(null != user){
			criteria.add(Restrictions.eq("sponsor.id", user.getId()));
		}
		if(null != shopUser){
			criteria.add(Restrictions.eq("shopUser.id", shopUser.getId()));
		}
		if(null != areaManager){
			criteria.add(Restrictions.eq("areaManager.id", areaManager.getId()));
		}
		if(null != postType){
			criteria.add(Restrictions.eq("source", postType));
		}
		criteria.add(Restrictions.between("submitDate", DateUtil.getFirstdayLastdayMonthOne(new Date()), DateUtil.getFirstdayLastdayMonthQuarter(new Date())));
		criteria.add(Restrictions.eq("status", checkStockStatus));
		List<CheckStock> checkStocks = criteria.list();
		
		return checkStocks.size();
		
	}
	
	/**
	 * 查询最近盘库日期
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public String findCloseCheckStockDate(Long shopId,User user){
		
		Criteria criteria=csDao.createCriteria();
		criteria.addOrder(Order.desc("finishDate"));
		
		criteria.createCriteria("shop").add(Restrictions.eq("id", shopId));//设置店铺
		criteria.add(Restrictions.eq("source", user.getPost()));//盘库来源
		criteria.add(Restrictions.ge("finishDate", DateUtil.getFirstdayLastdayMonthOne(new Date())));//只查当前月
		List<CheckStock> list=criteria.list();
		if(!CommonUtil.isEmptyList(list)){
			return DateUtil.formatDate(list.get(0).getFinishDate(), "yyyy-MM-dd");
		}
		return "";
	}
	
	/**
	 * 获得当前用户权限范围内的所有店铺ID的数组
	 * @return
	 */
	public Set<Long> getAllShops(User user){
		Set<Long> set=new HashSet<Long>();
		List<Organization> orgList=organizationDao.findShopsByCurrentUser(user);
		if(orgList!=null){
			for(int i=0;i<orgList.size();i++){
				set.add(orgList.get(i).getObjectId());
			}
		}
		
		return set;
	}
	
	/*
	 * 获得区域经理名字
	 */
	public String getShopUserName(Long shopId){
		StringBuilder names = new StringBuilder();
		List<Organization> orgs = orgService.findUserDomainByShopId(shopId);
		if(orgs != null && orgs.size() > 0){
			for (Iterator<Organization> iterator = orgs.iterator(); iterator.hasNext();) {
				Organization org = iterator.next();
				names.append(org.getName());
				if(iterator.hasNext()){
					names.append(",");
				}
			}
		}
		return names.toString();
	}
	
	/*
	 * 获得驻店员名字
	 */
	public String findUserShopByShopId(Long shopId){
		StringBuilder names = new StringBuilder();
		List<Organization> orgs = orgService.findUserShopByShopId(shopId);
		if(orgs != null && orgs.size() > 0){
			for (Iterator<Organization> iterator = orgs.iterator(); iterator.hasNext();) {
				Organization org = iterator.next();
				names.append(org.getName());
				if(iterator.hasNext()){
					names.append(",");
				}
			}
		}
		return names.toString();
	}
}
